home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / bit / src / dither.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  5KB  |  194 lines

  1. /*
  2.  * $Id: dither.c,v 0.91 1994/02/20 00:53:05 zhao Pre-Release $
  3.  *
  4.  *. This file is part of BIT shareware package. After the two weeks of
  5.  *  free evaluation period, you are encouraged (required) to register
  6.  *  your copy for a small registration fee, which is $35 for personal use
  7.  *  and $50 for commercial, government and institutional use.
  8.  *
  9.  *  Copyright(c) 1993, 1994 by T.C. Zhao.
  10.  *  All rights reserved.
  11.  *
  12.  *  Permission to use, copy, and distribute this software in its entirety
  13.  *  for non-commercial purposes is hereby granted, provided that the
  14.  *  above shareware and copyright notices and this permission notice
  15.  *  appear in all copies and their documentation.
  16.  *
  17.  *  This software may be modified for your own use, but modified versions
  18.  *  may not be distributed without prior consent of the author.
  19.  *
  20.  *  This software is provided "as is" without expressed or implied
  21.  *  warranty of any kind.
  22.  *
  23.  *.
  24.  *
  25.  * All gray to B&W dithering routines
  26.  *
  27.  */
  28. #if !defined(lint) && defined(F_ID)
  29. char *id_dit = "$Id: dither.c,v 0.91 1994/02/20 00:53:05 zhao Pre-Release $";
  30. #endif
  31.  
  32. #include "bit.h"
  33. #include "lookup.h"        /* defines dmatrix8 */
  34.  
  35. /******************* local variables ******************/
  36.  
  37. static int dither_threshold = -1;
  38. static int bwmethod;        /* dithering method */
  39.  
  40. /****************** local functions *****************/
  41.  
  42. /* All conversion function prototypes **/
  43. typedef int (*bw_cnvt_t) (rgba_t **, int, int, bw_t **);
  44.  
  45. static int fs_dither(rgba_t **, int, int, bw_t **);
  46. static int ordered_dither(rgba_t **, int, int, bw_t **);
  47.  
  48. /**************************************************************
  49.  * Text for option choices called by SetUP
  50.  **************************************************************/
  51.  
  52. const char *
  53. bw_dither_string(void)
  54. {
  55.     return "Ask|Floyd-Steinberg|Ordered8";
  56. }
  57.  
  58. /* and its corresponding functions */
  59. static bw_cnvt_t bwcnvt[] =
  60. {
  61.     fs_dither, ordered_dither
  62. };
  63.  
  64. /* control from Setup: Index corresponding to bw_dither_string */
  65.  
  66. extern int halftone_method;
  67.  
  68. /***********************************************************
  69.  * Master driver will call this routine before initiating
  70.  * the conversion via calling img_half_toning
  71.  
  72.  ************************************************************/
  73. int
  74. pre_bw(void)
  75. {
  76.     static long mbwmethod = -1;
  77.     int method;
  78.  
  79.     if (halftone_method > 0)
  80.       {
  81.       bwmethod = halftone_method - 1;
  82.       return 0;
  83.       }
  84.  
  85.     /* choose interactively the dithering method */
  86.     if (mbwmethod < 0)
  87.     mbwmethod = defpup("HalftoneMethod %t|F-S|Ordered8|Cancel");
  88.  
  89.     if ((method = dopup(mbwmethod)) <= 0 || method == 3)
  90.     return -1;
  91.  
  92.     /* actual method */
  93.     bwmethod = method - 1;
  94.     return 0;
  95. }
  96.  
  97. /*************************************************************
  98.  * Dispatcher, taking care of whatever =>GRAY  conversion
  99.  *************************************************************/
  100.  
  101. int
  102. img_half_toning(IPTR im)
  103. {
  104.     bw_t **new;
  105.     CMPTR m = im->cmap;
  106.  
  107.     /* convert to gray first. Note this recurses */
  108.     if (img_convert_type(im, T_GRAY) < 0)
  109.     return -1;
  110.  
  111.     /* fake color map: 0 for black 1 for white */
  112.     im->colors = m->colors = 2;
  113.     m->ct[0][0] = m->ct[1][0] = m->ct[2][0] = 0;
  114.     m->ct[0][1] = m->ct[1][1] = m->ct[2][1] = PCMAXV;
  115.  
  116.     new = get_mat(im->h, im->w, sizeof(bw_t));
  117.     if (bwcnvt[bwmethod] (im->mraster, im->h, im->w, new) < 0)
  118.     return -1;
  119.     return fill_image_struct(im, new, im->h, im->w, T_BW);
  120. }
  121.  
  122. /*************************************************************
  123.  * Ordered dither. The input matrix MUST be in RGB(gray)
  124.  *************************************************************/
  125.  
  126. static int
  127. ordered_dither(rgba_t **mat, int h, int w, bw_t **mm)
  128. {
  129.     register rgba_t *ras;
  130.     register bw_t *m;
  131.     register short *dm;
  132.     register int i, j;
  133.  
  134.     for (j = 0; j < h; j++)
  135.       {
  136.       dm = dmatrix8[j % 16];
  137.       for (i = 0, m = mm[j], ras = mat[j]; i < w; i++, ras++, m++)
  138.           *m = get_R(*ras) >= dm[i % 16];
  139.       }
  140.     return 0;
  141. }
  142.  
  143. /*************************************************************
  144.  * Floyd-Steiberg
  145.  *************************************************************/
  146. static int
  147. fs_dither(rgba_t **mat, int h, int w, bw_t **mm)
  148. {
  149.     register bw_t *m;
  150.     register rgba_t *ras;
  151.     register int *thisrow, *nextrow, dither2;
  152.     register int i, j;
  153.     int **tmp, err;
  154.  
  155.     if (dither_threshold <= 0)
  156.     dither_threshold = PCMAXV / 2;
  157.  
  158.     /* to preserve the errors on the edge, has to get one more row */
  159.     tmp = get_mat(h + 1, w, sizeof(**tmp));
  160.  
  161.     ras = mat[0];
  162.     thisrow = tmp[0];
  163.     for (nextrow = thisrow + h * w; thisrow < nextrow; thisrow++, ras++)
  164.     *thisrow = get_R(*ras);
  165.  
  166.     /*
  167.      * because we have the raster in a consecutive array, we got the edge
  168.      * errors right for free
  169.      */
  170.  
  171.     dither2 = PCMAXV;
  172.     for (i = 0; i < h; i++)
  173.       {
  174.       thisrow = tmp[i];
  175.  
  176.       /* can't have it run to h 'cause nextrow[j+1] will be wrong */
  177.  
  178.       if (i < h - 1)
  179.           nextrow = tmp[i + 1];
  180.  
  181.       for (m = mm[i], j = 0; j < w; j++, m++)
  182.         {
  183.         err = thisrow[j] -
  184.             ((*m = thisrow[j] >= dither_threshold) ? dither2 : 0);
  185.         thisrow[j + 1] += (err * 7) / 16;
  186.         nextrow[j - 1] += (err * 3) / 16;
  187.         nextrow[j] += (err * 5) / 16;
  188.         nextrow[j + 1] += err / 16;
  189.         }
  190.       }
  191.     free_mat(tmp);
  192.     return 0;
  193. }
  194.